package com.ruoyi.framework.task;

import com.ruoyi.project.system.domain.SysDoctor;
import com.ruoyi.project.system.domain.TempWeekDaily;
import com.ruoyi.project.system.mapper.SysDoctorMapper;
import com.ruoyi.project.system.mapper.TempWeekDailyMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 近一周医生值班数据生成任务
 * Bean名称：weeklyScheduleTask1（Ruoyi界面配置时需用此名称）
 */
@Component("weeklyScheduleTask1")
public class WeeklyScheduleTask {
    private static final Logger log = LoggerFactory.getLogger(WeeklyScheduleTask.class);

    @Autowired
    private SysDoctorMapper sysDoctorMapper;

    @Autowired
    private TempWeekDailyMapper weekDailyMapper;

    private static final SimpleDateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    // time_id与“星期+上下午”映射（1-14对应一周14个时段）
    private static final Map<Integer, String> TIME_ID_MAP = new HashMap<Integer, String>() {{
        put(1, "周一上午"); put(2, "周一下午");
        put(3, "周二上午"); put(4, "周二下午");
        put(5, "周三上午"); put(6, "周三下午");
        put(7, "周四上午"); put(8, "周四下午");
        put(9, "周五上午"); put(10, "周五下午");
        put(11, "周六上午"); put(12, "周六下午");
        put(13, "周日上午"); put(14, "周日下午");
    }};

    @Transactional(rollbackFor = Exception.class)
    public void generateWeeklySchedule() {
        log.info("===== 开始生成近一周医生值班数据 =====");

        try {
            weekDailyMapper.truncateTable();
            log.info("===== 开始删除昨日的值班记录 =====");
            Date today = new Date();
            log.info("基准日期：{}（星期{}）", DATE_FORMAT.format(today), getWeekStr(today));

            List<TempWeekDaily> weekDataList = new ArrayList<>();
            for (Map.Entry<Integer, String> entry : TIME_ID_MAP.entrySet()) {
                int timeId = entry.getKey();
                String timeDesc = entry.getValue();

                Date targetDate = calculateTargetDate(today, timeId);
                if (targetDate == null) {
                    log.warn("time_id={}（{}）：无法计算对应日期，跳过", timeId, timeDesc);
                    continue;
                }

                Date datetime = generateDatetime(targetDate, timeDesc.contains("上午"));
                List<SysDoctor> doctors = sysDoctorMapper.selectByTimeId(timeId);
                log.info("time_id={}（{}）：对应日期={}，查询到{}名值班医生", 
                         timeId, timeDesc, DATE_FORMAT.format(targetDate), doctors.size());

                // 在循环组装值班数据时，修改 currentDate_ 赋值逻辑（WeeklyScheduleTask.java 第89行左右）
            for (SysDoctor doctor : doctors) {
                // 跳过ID为空或姓名为空的无效医生
                if (doctor.getId() == null || doctor.getDoctor() == null || doctor.getDoctor().trim().isEmpty()) {
                    log.warn("跳过无效医生：ID={}，姓名={}", doctor.getId(), doctor.getDoctor());
                    continue;
                }

                TempWeekDaily record = new TempWeekDaily();
                record.setDatetime(datetime); // 值班时间（已确保不为空）
                record.setDoctorId(doctor.getId());
                record.setDoctorName(doctor.getDoctor().trim());
                record.setDepartment(doctor.getDepartment() != null ? doctor.getDepartment().trim() : "未知科室");
                record.setTitle(doctor.getTitle() != null ? doctor.getTitle().trim() : "未知职称");
                String schedule = doctor.getSchedule() != null ? doctor.getSchedule().trim() : "8:00-18:00";
                record.setScheduleText(timeDesc + " " + schedule);
                record.setRemaining(doctor.getRemaining() > 0 ? doctor.getRemaining() : 10);
                record.setTimeId(timeId);
                
                // 核心修复1：强制给 currentDate_ 赋值，并用 Objects.requireNonNull 避免 null
                record.setCurrentDate(Objects.requireNonNull(targetDate, "currentDate_ 不能为 null")); 
                
                weekDataList.add(record);
        }
            }

            if (!weekDataList.isEmpty()) {
                weekDailyMapper.batchInsert(weekDataList);
                log.info("近一周值班数据生成完成！共{}条记录", weekDataList.size());
            } else {
                log.warn("未查询到任何有效值班医生数据，temp_week_daily表为空");
            }

        } catch (Exception e) {
            log.error("生成近一周值班数据失败！", e);
            throw new RuntimeException("值班数据生成异常，事务已回滚", e);
        } finally {
            log.info("===== 近一周值班数据生成流程结束 =====");
        }
    }

    /**
     * 修复后的核心方法：计算time_id对应的实际日期（近7天内）
     * 逻辑：先统一星期编码，再计算偏移量，确保目标日期在基准日±6天内（近7天）
     */
    private Date calculateTargetDate(Date today, int timeId) {
        try {
            Calendar cal = Calendar.getInstance();
            cal.setTime(today);
            int todayCalendarWeek = cal.get(Calendar.DAY_OF_WEEK); // Calendar规则：1=周日，2=周一，...，7=周六

            // 1. 统一星期编码：将Calendar的1-7转换为 1=周一、2=周二、...、6=周六、7=周日（与TIME_ID_MAP一致）
            int todayUnifiedWeek = todayCalendarWeek == 1 ? 7 : todayCalendarWeek - 1;
            log.debug("基准日：{} → Calendar星期={} → 统一后星期={}", 
                      DATE_FORMAT.format(today), todayCalendarWeek, todayUnifiedWeek);

            // 2. 根据time_id获取目标星期（1=周一，2=周二，...，7=周日）
            int targetUnifiedWeek = (timeId + 1) / 2; // time_id=1→1，2→1；...13→7，14→7
            log.debug("time_id={} → 目标统一星期={}", timeId, targetUnifiedWeek);

            // 3. 计算偏移量：目标星期 - 基准日统一星期（结果可能为负，需修正为0-6天）
            int offset = targetUnifiedWeek - todayUnifiedWeek;
            // 修正逻辑：如果偏移量为负，说明目标星期在下周，需加7天（确保在近7天内）
            offset = offset < 0 ? offset + 7 : offset;

            // 4. 计算目标日期（基准日 + 偏移量）
            cal.add(Calendar.DATE, offset);
            Date targetDate = cal.getTime();
            log.debug("基准日={}，偏移量={}天 → 目标日期={}", 
                      DATE_FORMAT.format(today), offset, DATE_FORMAT.format(targetDate));

            return targetDate;

        } catch (Exception e) {
            log.error("计算time_id={}的目标日期失败", timeId, e);
            return null;
        }
    }

    /**
     * 生成精确到时分的datetime字段
     */
    private Date generateDatetime(Date date, boolean isMorning) {
        try {
            String dateStr = DATE_FORMAT.format(date);
            String timeStr = isMorning ? "08:00:00" : "14:00:00";
            return DATETIME_FORMAT.parse(dateStr + " " + timeStr);
        } catch (ParseException e) {
            log.error("生成datetime失败，日期={}，是否上午={}", date, isMorning, e);
            return new Date();
        }
    }

    /**
     * 辅助方法：将日期转换为中文星期（用于日志打印）
     */
    private String getWeekStr(Date date) {
        String[] weekArr = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int weekIndex = cal.get(Calendar.DAY_OF_WEEK) - 1;
        return weekArr[weekIndex];
    }
}